﻿// MainWindow
// 
// Main window of FMLScan application
// 
// FLMScan - Featured by FabLab Munich

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.Ports;
using System.Drawing;
using System.Windows.Threading;
using FLMScan.Exception;

namespace FLMScan
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IFLMScanView
    {
        private event EventHandler ViewLoaded;
        private event EventHandler ViewClosed;

        private static UnhandledExceptionHandler exceptionHandler;
                   
        public MainWindow()
        {                        
            InitializeComponent();

            // pre-allocate exception handler
            exceptionHandler = UnhandledExceptionHandler.Instance();

            App.Current.DispatcherUnhandledException +=
                new DispatcherUnhandledExceptionEventHandler(MainWindow.Dispatcher_UnhandledException);
        }

        private static void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            exceptionHandler.HandleException(sender, e);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if (ViewLoaded != null)
            {
                ViewLoaded(this, EventArgs.Empty);
            }
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            if (ViewClosed != null)
            {
                ViewClosed(this, EventArgs.Empty);
            }
        }

        #region Getters and Setters

        public delegate void SetPictureBoxDelegate(Bitmap bitmap);

        private void SetPictureBox(Bitmap bitmap)
        {
            imageWebcam.Source = getScaledImage(bitmap);                
        }

        System.Drawing.Bitmap IFLMScanView.PictureBoxImage 
        {
            set
            {                
                imageWebcam.Dispatcher.Invoke(new SetPictureBoxDelegate(SetPictureBox), new object[] { value });                                
            }
        }        

        // TBD: think about different pattern for invoke
        // pattern taken from
        // http://www.codeproject.com/KB/threads/ThreadingDotNet5.aspx
        //  if( textBlock2.CheckAccess())
        //  {
        //      imageLaserPower.Source = ...
        //  }
        //  else
        //  {
        //      Dispatcher.Invoke(DispatcherPriority.Send, (Action)delegate { imageLaserPower.Source = ... });                    
        //  }
                                               
        #endregion

        #region EventHandlers

        event EventHandler IFLMScanView.ViewLoaded
        {
            add { ViewLoaded += value; }
            remove { ViewLoaded -= value; }
        }

        event EventHandler IFLMScanView.ViewClosed
        {
            add { ViewClosed += value; }
            remove { ViewClosed -= value; }
        }
        
        #endregion
        
        #region Helpers
        
        private BitmapSource getScaledImage(System.Drawing.Bitmap bitmap)
        {
            System.Drawing.Bitmap originalBitmap = bitmap;            
            System.Drawing.Size imageSize = GenerateImageDimensions
                ((int)originalBitmap.Width, (int)originalBitmap.Height
                , (int)this.canvasWebcam.ActualWidth, (int)this.canvasWebcam.ActualHeight);

            Int32Rect sourceRect = new Int32Rect(0, 0, originalBitmap.Width, originalBitmap.Height);        
            BitmapSource scaledImage = CreateBitmapSourceFromBitmap(bitmap, sourceRect, imageSize);
            

            return scaledImage;
        }

        public System.Drawing.Size GenerateImageDimensions(int sourceWidth, int sourceHeight, int destinationWidth, int destinationHeight)
        {
            double scaleFactor = 0; // factor to use for scaling the image            

            // ratio of source width/height is portrait format
            if (sourceHeight > sourceWidth)
            {
                if (destinationHeight > destinationWidth)
                    scaleFactor = (double)destinationWidth / (double)sourceWidth;
                else
                    scaleFactor = (double)destinationHeight / (double)sourceHeight;
            }
            // ratio of source width/height is landscape format
            else
            {
                if (destinationHeight > destinationWidth)
                    scaleFactor = (double)destinationWidth / (double)sourceWidth;
                else
                    scaleFactor = (double)destinationHeight / (double)sourceHeight;
            }

            return new System.Drawing.Size((int)(sourceWidth * scaleFactor), (int)(sourceHeight * scaleFactor));
        }

        // TBD: modify code as described in article in order to avoid handle leak
        // taken from: http://www.codeproject.com/KB/WPF/BitmapToBitmapSource.aspx        
        public BitmapSource CreateBitmapSourceFromBitmap(Bitmap bitmap, Int32Rect sourceRect, System.Drawing.Size imageSize)
        {
            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                bitmap.GetHbitmap(),
                IntPtr.Zero,
                sourceRect,
                BitmapSizeOptions.FromWidthAndHeight(imageSize.Width, imageSize.Height));
        }        

        #endregion

    }
}
